package com.gist.cithub.service.utils;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gist.cithub.service.entity.InforEntity;

import java.sql.SQLOutput;
import java.time.Duration;
import java.time.Instant;
import java.util.*;

import static java.lang.Thread.sleep;

public class ConductorAPI {
    private String ip;
    private String port;
    String url;
    private HashMap<String,String> serivceInfor;

    static HttpRequestor requestor = new HttpRequestor();

    public ConductorAPI(String ip, String port){
        this.ip = ip;
        this.port = port;
        url = "http://" + ip + ":" + port + "/api/";
    }

    public String addWorkFlow(List<InforEntity> list){
        StringBuffer sb = new StringBuffer();
        String res = "workflow" + new Date().getTime();
        sb.append("{\"name\":\"" + res + "\",\n");
        sb.append("\"description\": \"a workflow\",\n" );
        sb.append("\"version\": 1,\n");
        sb.append("\"tasks\":[\n");
        for(int i = 0; i < list.size(); i++){
            sb.append("{\"name\":\"login\",\n");
            sb.append("\"taskReferenceName\":\"task" + i + "\",\n");
            sb.append("\"inputParameters\":{\n");
            sb.append("\"http_request\":{\n");
            sb.append("\"method\": \"POST\",\n");
            sb.append("\"uri\": \"" + list.get(i).getUrl() + "\"\n");
            JSONObject parameters = xputJsonFormat(list.get(i).getInputFormat());
            System.out.println(parameters.toJSONString());
            int n = parameters.size(), index = 0;
            if(n != 0) {
                sb.append(",\"body\": {\n");
                for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                    String key = entry.getKey();
                    boolean got = false;
                    for (int j = i - 1; j >= 0; j--) {
                        JSONObject tmp = xputJsonFormat(list.get(j).getOutputFormat());
                        System.out.println(tmp.toJSONString());
                        for (Map.Entry<String, Object> entry1 : tmp.entrySet()) {
                            if (key.equals(entry1.getKey())) {
                                got = true;
                                sb.append("\"" + key + "\": \"${task" + j + ".output.response.body." + key + "}\"");
                                break;
                            }
                        }
                        if (got)
                            break;
                    }
                    if (!got)
                        sb.append("\"" + key + "\": \"${workflow.input." + key + "}\"");
                    index++;
                    if (index != n)
                        sb.append(",");
                    sb.append("\n");
                }
                sb.append("}");
            }
            sb.append("}},\n\"type\" : \"HTTP\"}");
            if(i != list.size() - 1)
                sb.append(",\n");
        }
        sb.append("],\n\"schemaVersion\": 2}");
        System.out.println(sb.toString());
        String URL = url + "metadata/workflow";
        try {
            requestor.doRequest("POST", URL, sb);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        return res;

    }
    public JSONObject xputJsonFormat(String inputFormat){
        inputFormat=inputFormat.replaceAll("\r","");
        String []inputArray=inputFormat.split("\n");
        JSONObject inputJsonFormat=new JSONObject();
        for(int i=0;i<inputArray.length;i++)
        {
            String []temp=inputArray[i].split(";");
            if(temp.length>3)
            {
                String valueOfExample="";
                for(int j=3;j<temp.length;j++)
                {
                    valueOfExample+=temp[j]+";";
                }
                temp[3]=valueOfExample.substring(0,valueOfExample.length()-1);
            }
            String example="";
            if(temp[3].indexOf("##")!=-1) {
                example=temp[3].split("##")[0];
            }
            else {
                example=temp[3];
            }
            if(temp[1]=="int") {
                inputJsonFormat.put(temp[0], JSONObject.parse(example));
            }
            else if(temp[1]=="int[]")
            {
                inputJsonFormat.put(temp[0], JSONObject.parse(example));
            }
            else if(temp[1]=="int[][]")
            {
                inputJsonFormat.put(temp[0], JSONObject.parse(example));
            }
            else if(temp[1]=="string[]")
            {
                inputJsonFormat.put(temp[0], JSONObject.parse(example));
            }
            else if(temp[1]=="string[][]")
            {
                inputJsonFormat.put(temp[0], JSONObject.parse(example));
            }
            else {
                inputJsonFormat.put(temp[0], example);
            }
        }
        return  inputJsonFormat;
    }

    /**
     * same
     * @param list 服务列表
     * @param input
     * @return workname
     */
    public String addForkWorkFlow(List<InforEntity> list, JSONObject input){
        serivceInfor=new HashMap<String,String>();
        StringBuffer sb = new StringBuffer();
        String res = "workflow" + new Date().getTime();
        sb.append("{\"name\":\"" + res + "\",\n");
        sb.append("\"description\": \"a workflow\",\n" );
        sb.append("\"version\": 1,\n");
        sb.append("\"tasks\":[{\n");
        sb.append("\"name\": \"fork\",\n");
        sb.append("\"taskReferenceName\": \"fork\",\n");
        sb.append("\"type\": \"FORK_JOIN\",\n");
        sb.append("\"forkTasks\" :[\n");
        for(int i = 0; i < list.size(); i++){
            sb.append("[{\"name\":\"login\",\n");
            sb.append("\"taskReferenceName\":\"task" + i + "\",\n");
            sb.append("\"inputParameters\":{\n");
            sb.append("\"http_request\":{\n");
            sb.append("\"method\": \"POST\",\n");
            sb.append("\"uri\": \"" + list.get(i).getUrl() + "\"\n");
            serivceInfor.put(list.get(i).getUrl(),list.get(i).getTitle());
            String parameters = input.toJSONString();
            if(parameters.length() > 2){
                sb.append(",\"body\": " + parameters);
            }
            sb.append("}},\n\"type\" : \"HTTP\"}]\n");
            if(i != list.size() - 1)
                sb.append(",");
        }
        sb.append("]}, \n{\"name\": \"join\",\n");
        sb.append("\"taskReferenceName\": \"join\",");
        sb.append("\"type\":\"JOIN\"}");
        sb.append("],\n\"schemaVersion\": 2}");
        System.out.println(sb.toString());
        String URL = url + "metadata/workflow";
        try {
            requestor.doRequest("POST", URL, sb);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        return res;
    }

    public String startWorkFlow(String name, StringBuffer input){
        String URL = url + "workflow/" + name;
        String res = "";
        try {
            res = requestor.doRequest("POST", URL, input);
        } catch (Exception e) {
            e.printStackTrace();
            res =  "fail";
        }
        return res;
    }

    /**
     * diff
     * @param id
     * @return
     */
    public String getResult(String id){
        String URL = url + "workflow/" + id;
        System.out.println("getResult的URL是"+URL);
        try {
            System.out.println(URL);
            String res = requestor.doGet(URL);
            JSONObject jsonObject = JSONObject.parseObject(res);
//            System.out.println("jsonObject是"+jsonObject);
            Instant start=Instant.now();
            StringBuffer input=new StringBuffer("{}");
            int flag=0;
            while(jsonObject.getString("status").equals("RUNNING")){
                //System.out.println(res);
                sleep(200);
                long time=Duration.between(start, Instant.now()).getSeconds()*1000;
//                System.out.println();
                if(flag<1&&(time>100000))//防止死机
                {
                    if(restartWork(flag,id,input).equals("fail"))
                    {
                        res = requestor.doGet(URL);
                        jsonObject = JSONObject.parseObject(res);
                        flag++;
                        start=Instant.now();
                        continue;
                    }
                    flag++;
//                    start=Instant.now();
                    res = requestor.doGet(URL);
                    jsonObject = JSONObject.parseObject(res);
                }
                else {
                    res = requestor.doGet(URL);
                    jsonObject = JSONObject.parseObject(res);
                }
            }
            if(!jsonObject.getString("status").equals("COMPLETED"))
                return "failed";
            res = jsonObject.getString("tasks");
            JSONArray jsonArray = JSONArray.parseArray(res);
            JSONObject result = new JSONObject();
            StringBuffer sb = new StringBuffer();
            sb.append("{\"result\":[");
            for(int i = 0; i < jsonArray.size(); i++){
                JSONObject tmp = (JSONObject) jsonArray.get(i);
                //System.out.println(tmp.toJSONString());
                tmp = (JSONObject)tmp.get("outputData");
                tmp = (JSONObject) tmp.get("response");
                res = tmp.getString("body");
                //result.put("\"s" + i + "\"", res);
                sb.append(res);
                if(i != jsonArray.size() - 1)
                    sb.append(",");
            }
            sb.append("]}");
            System.out.println(sb.toString());

            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();

        }
        return "failed";
    }

    /**
     * same
     * @param id
     * @return
     */
    public String getForkTaskResult(String id){
        String URL = url + "workflow/" + id;
        try {
            String res = requestor.doGet(URL);
            System.out.println("res:"+res);
            System.out.println(URL);
            JSONObject jsonObject = JSONObject.parseObject(res);
            Instant start=Instant.now();
            StringBuffer input=new StringBuffer("{}");
            int flag=0;
            while(jsonObject.getString("status").equals("RUNNING")){
                sleep(200);
                long time=Duration.between(start, Instant.now()).getSeconds()*1000;
//                System.out.println();
                if(flag<1&&(time>100000))//防止死机
                {
                    if(restartWork(flag,id,input).equals("fail"))
                    {
                        res = requestor.doGet(URL);
                        jsonObject = JSONObject.parseObject(res);
                        flag++;
                        start=Instant.now();
                        continue;
                    }
                    flag++;
//                    start=Instant.now();
                    res = requestor.doGet(URL);
                    jsonObject = JSONObject.parseObject(res);
                }
                else {
                    res = requestor.doGet(URL);
                    jsonObject = JSONObject.parseObject(res);
                }
            }
            if(!jsonObject.getString("status").equals("COMPLETED"))
                return "failed";
            res = jsonObject.getString("tasks");
            String serviceName="";
            JSONArray jsonArray = JSONArray.parseArray(res);
            JSONObject result = new JSONObject();
            StringBuffer sb = new StringBuffer();
            sb.append("{\"result\":[");
            for(int i = 1; i < jsonArray.size() - 1; i++){
                JSONObject tmp = (JSONObject) jsonArray.get(i);
                JSONObject tmp2 = (JSONObject) jsonArray.get(i);
                System.out.println(tmp.toJSONString());
                tmp = (JSONObject)tmp.get("outputData");
                tmp2=(JSONObject)tmp2.get("inputData");
                tmp2=(JSONObject)tmp2.get("http_request");
                tmp = (JSONObject) tmp.get("response");//报错
                res = tmp.getString("body");
                serviceName=serivceInfor.get(tmp2.getString("uri"));
                res=res.substring(0,res.length()-1);
                //result.put("\"s" + i + "\"", res);
                sb.append(res);
                sb.append(",\"title\":\""+serviceName+"\"}");
                if(i != jsonArray.size() - 2)
                    sb.append(",");
            }
            sb.append("]}");
            System.out.println(sb.toString());

            return sb.toString();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return "failed";
    }

    /**
     * 重新运行
     * @param id
     * @param input
     * @return
     */
    public String restartWork(int times,String id,StringBuffer input)  {
        String URLend=url+"workflow/"+id;
        String URL=url+"workflow/"+id+"/restart";
        System.out.println("第"+times+"次重新执行"+URL);
        String res = "";
        try {
            res=requestor.doRequest("DELETE",URLend,input);
            res = requestor.doRequest("POST",URL,input);
            sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
            res = "fail";
            return res;
        }
        System.out.println("重启成功");
        return res;

    }


//    public static void main(String[] args){
//        List<Service> list = new ArrayList<>();
//        Service service1 = new Service();
//        service1.setUrl("http://114.212.82.36:8080/user/login?userName=jinchun&password=1");
//        service1.setInputFormat("{}");
//        service1.setOutputFormat("{\"c\":\"c\", \"d\":\"d\"}");
//
//        Service service2 = new Service();
//        service2.setUrl("http://114.212.82.36:8080/user/viewInfo/1");
//        service2.setInputFormat("{}");
//        list.add(service1);
//        list.add(service2);
//
//        JSONObject input = new JSONObject();
//        input.put("parameters", 2);
//        input.put("values", new int[]{2,2,2,2});
//
//        ConductorAPI conductorAPI = new ConductorAPI("114.212.82.228", "8080");
//        // String name = conductorAPI.addForkWorkFlow(list, input);
//        //System.out.println(name);
//        //String id = ConductorAPI.startWorkFlow(name, new StringBuffer("{}"));
//        //System.out.println(id);
//        String id = "8040005a-33e9-4fbc-b026-9dfeb0151552";
//        String res = conductorAPI.getForkTaskResult(id);
//        System.out.println(res);
//    }
}
